/**
 * 
 */
package com.roshan.web.security.cryptography;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import sun.misc.BASE64Decoder;

@SuppressWarnings("restriction")
@Component
public class RoarCryptographyProvider implements IRoarCryptographyProvider {

    private static final Logger logger = Logger.getLogger(RoarCryptographyProvider.class);

    private static ThreadLocal<Cipher> ecipher = new ThreadLocal<Cipher>();

    private static ThreadLocal<Cipher> dcipher = new ThreadLocal<Cipher>();

    private @Value("${roar.security.cipher.algorithm}")
    String encryptionAlgorithm;

    private @Value("${roar.security.cipher.key}")
    String encryptionKey;

    private @Value("${roar.security.string.encoder}")
    String charEncoder;

    public Cipher getEcipher() {
        return ecipher.get();
    }

    public Cipher getDcipher() {
        return dcipher.get();
    }

    private void init() throws Exception {
        try {

            SecretKey key = new SecretKeySpec(new BASE64Decoder().decodeBuffer(this.encryptionKey),
                    this.encryptionAlgorithm);

            ecipher.set(Cipher.getInstance(this.encryptionAlgorithm));
            dcipher.set(Cipher.getInstance(this.encryptionAlgorithm));
            ecipher.get().init(Cipher.ENCRYPT_MODE, key);
            dcipher.get().init(Cipher.DECRYPT_MODE, key);

        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
            throw ex;
        }
    }

    @Override
    public String encrypt(String token) {
        try {
            if (getEcipher() == null) {
                init();
            }

            byte[] encoder = token.getBytes(this.charEncoder);
            byte[] enc = getEcipher().doFinal(encoder);
            return org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(enc);

        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public String encryptByteArray(byte[] arrToken) {
        try {
            if (getEcipher() == null) {
                init();
            }

            byte[] enc = getEcipher().doFinal(arrToken);
            return org.apache.commons.codec.binary.Base64.encodeBase64URLSafeString(enc);

        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    @Override
    public String decrypt(String token) {
        try {
            if (getDcipher() == null) {
                init();
            }
            byte[] dec = org.apache.commons.codec.binary.Base64.decodeBase64(token);
            byte[] decoder = getDcipher().doFinal(dec);
            return new String(decoder, this.charEncoder);

        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public byte[] decryptToArray(String token) {
        try {
            if (getDcipher() == null) {
                init();
            }
            byte[] dec = org.apache.commons.codec.binary.Base64.decodeBase64(token);
            byte[] decoder = getDcipher().doFinal(dec);
            return decoder;

        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

}
